//
//  GRWebViewContainer.m
//  XJMF
//
//  Created by sqkj on 2022/3/1.
//

#import "GRWebViewContainer.h"
#import "GRWebViewContainer.h"
#import <Masonry.h>
#import "ISEParams.h"
#import "ISEResult.h"
#import <MJExtension/MJExtension.h>
#import "NSString+KSURLEncoded.h"
#import "ISEResultXmlParser.h"
#import "XMLReader.h"
#import "PcmPlayer.h"
 
static NSString *kAndroidStartRecord = @"androidStartRecord";
static NSString *kRecordFinishCallBack = @"recordFinishCallBack";


@implementation GRScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}

@end

static NSString *const TITLE_KEYPATH = @"title";
static NSString *const PROGR_KEYPATH = @"estimatedProgress";
static NSString *const LOADING_KEYPATH = @"loading";

@interface GRWebViewContainer ()<WKUIDelegate,WKNavigationDelegate,IFlySpeechEvaluatorDelegate,IFlyPcmRecorderDelegate,WKScriptMessageHandler,ISEResultXmlParserDelegate,IFlySpeechSynthesizerDelegate>

@property (nonatomic, strong) IFlySpeechEvaluator *iFlySpeechEvaluator;
@property (nonatomic, strong) ISEParams *iseParams;
@property (nonatomic,strong) IFlyPcmRecorder *pcmRecorder;//PCM Recorder to be used to demonstrate Audio Stream Evaluation.
@property (nonatomic, strong) GRScriptMessageDelegate *scripteDelegate;
@property (nonatomic,copy) NSString *recordWord;
@property (nonatomic,assign) BOOL isStartRecord;
@property (nonatomic,assign) BOOL isStopRecord;
@property (nonatomic, strong) ISEResultXmlParser *xmlParser;
@property (nonatomic, strong) IFlySpeechSynthesizer * iFlySpeechSynthesizer;
@property (nonatomic, strong) NSString *uriPath;
@property (nonatomic, strong) PcmPlayer *audioPlayer;

 

@end

@implementation GRWebViewContainer

- (GRScriptMessageDelegate *)scripteDelegate {
    if (!_scripteDelegate) {
        _scripteDelegate = [[GRScriptMessageDelegate alloc] initWithDelegate:self];
    }
    return _scripteDelegate;
}

#pragma mark -

- (void)bindViewModel{
    [self setupConfig];
    [self addKVO];
}

- (void)setupViews{
    [self addSubview:self.webView];
    [self addSubview:self.progressView];
}

- (void)updateConstraints{
//    [self.progressView mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.top.leading.trailing.mas_equalTo(0);
//        make.height.mas_equalTo(2);
//    }];
    [self.webView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(0);
    }];
    [super updateConstraints];
}

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    if ([message.name isEqualToString:@"log"]) {
        NSLog(@"console.log:%@",message.body);
    }
    if ([message.name isEqualToString:@"bridgeTest"]) {
        NSString *bodyString = KSSAFE_CAST(message.body, NSString);
        NSDictionary *dic = KSSAFE_CAST([bodyString mj_JSONObject], NSDictionary);
        NSString *actionName = KSSAFE_CAST(dic[@"name"], NSString);
        if (actionName.length > 0) {
            if ([actionName isEqualToString:@"startRecord"]){
                NSString *name = dic[@"data"][@"name"];
                if (name.length > 0){
                    NSInteger time1 = [dic[@"data"][@"time1"]intValue];
                    NSInteger time2 = [dic[@"data"][@"time2"]intValue];
                    NSInteger time3 = [dic[@"data"][@"time3"]intValue];
                    self.recordWord = name;
                    [self startRecord:time1 time2:time2 time3:time3];
                    self.isStartRecord = YES;
                    self.isStopRecord = NO;
                    [self.webView evaluateJavaScript:@"javascript:androidStartRecord()" completionHandler:^(id _Nullable data, NSError * _Nullable error) {

                   }];
                }
            }
            if ([actionName isEqualToString:@"stopRecord"]){
                [self stopRecord];
                self.isStartRecord = NO;
                self.isStopRecord = YES;
            }
            
            if ([actionName isEqualToString:@"startTTS"]){
                NSDictionary *dataDict = dic[@"data"];
                if (dataDict){
                    NSString *content = dataDict[@"content"];
                    NSString *voicer = dataDict[@"voicer"];
                    [self startTTS:content voicer:voicer];
                }
            }
        }
    }
}

#pragma mark -
- (void)webViewReloadNotificationAction:(NSNotification *)notification {
    [self.webView reload];
}

#pragma mark -
- (WKWebView *)webView{
    if (!_webView) {
        _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:self.defaultConfiguration];
//        _webView.backgroundColor = [UIColor colorWithRed: 246/255.0 green: 154/255.0 blue: 17/255.0 alpha:1.000];
//        _webView.scrollView.backgroundColor = [UIColor colorWithRed: 246/255.0 green: 154/255.0 blue: 17/255.0 alpha:1.000];
        NSString * consoleLog = @"console.log = (function(oriLogFunc){return function(str){oriLogFunc.call(console,str);window.webkit.messageHandlers.log.postMessage(str);}})(console.log);";
        WKUserScript *userScriptLog = [[WKUserScript alloc] initWithSource:consoleLog injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
        [_webView.configuration.userContentController addUserScript:userScriptLog];
        [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"bridgeTest"];
        [_webView.configuration.userContentController addScriptMessageHandler:self.scripteDelegate name:@"bridgeTest"];
        [_webView.configuration.userContentController addScriptMessageHandler:self.scripteDelegate name:@"log"];
        _webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    return _webView;
}

- (GRWebViewConfiguration *)defaultConfiguration{
    if (!_defaultConfiguration) {
        _defaultConfiguration = [GRWebViewConfiguration defaultConfiguration];
    }
    return _defaultConfiguration;
}

- (UIProgressView *)progressView {
    if (!_progressView) {
        _progressView = [[UIProgressView alloc] init];
        _progressView.trackTintColor = [UIColor whiteColor];
        _progressView.progressTintColor = [UIColor blueColor];
    }
    return _progressView;
}

- (void)dealloc {
    [self.webView removeObserver:self forKeyPath:TITLE_KEYPATH];
    [self.webView removeObserver:self forKeyPath:PROGR_KEYPATH];
    [self.webView removeObserver:self forKeyPath:LOADING_KEYPATH];
}

#pragma mark - Public Methed

- (void)loadURL:(NSURL *)URL{
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL
                                                  cachePolicy:NSURLRequestUseProtocolCachePolicy
                                              timeoutInterval:30];
    [self.webView loadRequest:request];
}

- (void)loadURLstr:(NSString *)url {
    NSAssert(url, @"URL can not be nil");
    [self loadURL:[NSURL URLWithString:url]];
}

- (void)loadLocalHtmlFileName:(NSString *)htmlName {
    NSURL *htmlPath = [[NSBundle mainBundle] URLForResource:htmlName withExtension:@"html"];
    NSString *contentString = [[NSString alloc] initWithContentsOfURL:htmlPath
                                                             encoding:NSUTF8StringEncoding
                                                                error:nil];
    [self.webView loadHTMLString:contentString baseURL:[[NSBundle mainBundle] bundleURL]];
}

#pragma mark - Private Method

- (void)setupConfig {
    self.webView.UIDelegate = self;
    self.webView.navigationDelegate = self;
    
    
    //  设置允许滑动返回手势，default is NO
    self.webView.allowsBackForwardNavigationGestures = YES;
    self.backgroundColor = [UIColor colorWithRed: 246/255.0 green: 154/255.0 blue: 17/255.0 alpha:1.000];
    [_webView evaluateJavaScript:@"document.body.style.backgroundColor=\"#F3880A\"" completionHandler:nil];
    self.iseParams = [ISEParams fromUserDefaults];

    // 获取评测对象单例
    _iFlySpeechEvaluator = [IFlySpeechEvaluator sharedInstance];
    _iFlySpeechEvaluator.delegate = self;
    // 设置训练参数
    // 清空参数
    [_iFlySpeechEvaluator setParameter:@"" forKey:[IFlySpeechConstant PARAMS]];
    // 设置评测采样率
    [self.iFlySpeechEvaluator setParameter:@"16000" forKey:[IFlySpeechConstant SAMPLE_RATE]];
    // 设置评测题目编码，如果是utf-8格式，请添加bom头，添加方式可参考demo。
    [self.iFlySpeechEvaluator setParameter:@"utf-8" forKey:[IFlySpeechConstant TEXT_ENCODING]];
    // 设置评测题目结果格式，目前仅支持xml
    [self.iFlySpeechEvaluator setParameter:@"xml" forKey:[IFlySpeechConstant ISE_RESULT_TYPE]];
    // 设置评测题型
    [self.iFlySpeechEvaluator setParameter:@"read_sentence" forKey:[IFlySpeechConstant ISE_CATEGORY]];
    // 设置评测语言
    [self.iFlySpeechEvaluator setParameter:@"en_us"
    forKey:[IFlySpeechConstant LANGUAGE]];
    // 设置评测结果级别
    [self.iFlySpeechEvaluator setParameter:@"complete" forKey:[IFlySpeechConstant ISE_RESULT_LEVEL]];
    // 设置流
    [self.iFlySpeechEvaluator setParameter:@"-1" forKey:[IFlySpeechConstant AUDIO_SOURCE]];
    [self.iFlySpeechEvaluator setParameter:@"en_vip" forKey:@"ent"]; // updated ise_flow
    [self.iFlySpeechEvaluator setParameter:@"0" forKey:@"plev"];
    [self.iFlySpeechEvaluator setParameter:@"ise" forKey:@"sub"];
    [self.iFlySpeechEvaluator setParameter:@"1" forKey:@"ise_unite"];
    [self.iFlySpeechEvaluator setParameter:@"entirety" forKey:@"rst"];
    [self.iFlySpeechEvaluator setParameter:@"syll_phone_err_msg;pitch;multi_dimension" forKey:@"extra_ability"];

    
    //Initialize recorder
    if (_pcmRecorder == nil){
        _pcmRecorder = [IFlyPcmRecorder sharedInstance];
    }
    _pcmRecorder.delegate = self;
    [_pcmRecorder setSample:@"16000"];
    [_pcmRecorder setSaveAudioPath:nil];    //no
    
    self.xmlParser=[[ISEResultXmlParser alloc] init];
    self.xmlParser.delegate=self;
    
    
    //URI TTS: -(void)synthesize:(NSString *)text toUri:(NSString*)uri
    //If uri is nil, the audio file is saved in library/cache by defailt.
    NSString *prePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    //Set the audio file name for URI TTS
    _uriPath = [NSString stringWithFormat:@"%@/%@",prePath,@"uri.pcm"];
    
    self.iFlySpeechSynthesizer = [IFlySpeechSynthesizer sharedInstance];
    _iFlySpeechSynthesizer.delegate = self;
    [_iFlySpeechSynthesizer setParameter:@"" forKey:[IFlySpeechConstant PARAMS]];
    NSString *resPath = [[NSBundle mainBundle] resourcePath];
    NSString *newResPath = [[NSString alloc] initWithFormat:@"%@/xtts/purextts_common.jet;%@/xtts/purextts_xiaoyan.jet",resPath,resPath];
    [[IFlySpeechUtility getUtility] setParameter:@"tts" forKey:[IFlyResourceUtil ENGINE_START]];
    [_iFlySpeechSynthesizer setParameter:newResPath forKey:@"tts_res_path"];
    
    //set speed,range from 1 to 100.
    [_iFlySpeechSynthesizer setParameter:@"50" forKey:[IFlySpeechConstant SPEED]];

    //set volume,range from 1 to 100.
    [_iFlySpeechSynthesizer setParameter:@"50" forKey:[IFlySpeechConstant VOLUME]];

    //set pitch,range from 1 to 100.
    [_iFlySpeechSynthesizer setParameter:@"50" forKey:[IFlySpeechConstant PITCH]];

    //set sample rate
    [_iFlySpeechSynthesizer setParameter:@"16000" forKey:[IFlySpeechConstant SAMPLE_RATE]];
    
    [_iFlySpeechSynthesizer setParameter:@"unicode" forKey:[IFlySpeechConstant TEXT_ENCODING]];
    
    [_iFlySpeechSynthesizer setParameter:@"cloud" forKey:[IFlySpeechConstant ENGINE_TYPE]];
    
    //set xtts params
    [_iFlySpeechSynthesizer setParameter:@"1" forKey:@"rdn"];
    [_iFlySpeechSynthesizer setParameter:@"0" forKey:@"effect"];
    [_iFlySpeechSynthesizer setParameter:@"0" forKey:@"rcn"];
    
    
}

-(void)resetBtnSatus:(IFlySpeechError *)errorCode{
    
    if(errorCode && errorCode.errorCode!=0){
 
    }else{
 
    }
}
- (void)addKVO {
    [self.webView addObserver:self
           forKeyPath:PROGR_KEYPATH
              options:NSKeyValueObservingOptionNew
              context:nil];
    
    [self.webView addObserver:self
           forKeyPath:TITLE_KEYPATH
              options:NSKeyValueObservingOptionNew
              context:nil];
        
    [self.webView addObserver:self
           forKeyPath:LOADING_KEYPATH
              options:NSKeyValueObservingOptionNew
              context:nil];
}

- (void)observeValueForKeyPath:(nullable NSString *)keyPath
                      ofObject:(nullable id)object
                        change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change
                       context:(nullable void *)context {
    if ([keyPath isEqualToString:TITLE_KEYPATH]) {
        
        NSString *changeValue = (NSString *)change[NSKeyValueChangeNewKey];
        if (self.titleDidChangeBlock) {
            self.titleDidChangeBlock(changeValue);
        }
        return;
    }
    
    if ([keyPath isEqualToString:PROGR_KEYPATH] && object == self.webView) {
        double progress = [change[NSKeyValueChangeNewKey] doubleValue];
        NSLog(@"%f",progress);
        [self.progressView setProgress:progress animated:YES];
        self.progressView.hidden = !(progress < 1);
        if (self.progressChangeBlock) {
            self.progressChangeBlock(progress);
        }
        return;
    }
    
    if ([keyPath isEqualToString:LOADING_KEYPATH]) {
        BOOL show = [change[NSKeyValueChangeNewKey] boolValue];
        if (self.loadingShowBlock) {
            self.loadingShowBlock(show);
        }
        return;
    }

}


#pragma mark - WKNavigationDelegate
//  Web内容开始在网页视图中加载时调用。
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    if (self.webViewStartLoadBlock) {
        self.webViewStartLoadBlock(webView);
    }
}

//  当Web视图收到服务器重定向时调用。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    //** tel
    UIApplication *application = [UIApplication sharedApplication];
    NSURL         *url = navigationAction.request.URL;
    
    // 阻止 加载 “空”页面
    if ([url.absoluteString isEqualToString:@"about:blank"]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    if (!navigationAction.targetFrame) {
        if ([application canOpenURL:url]) {
            [application openURL:url options:@{} completionHandler:^(BOOL success) {
                decisionHandler(WKNavigationActionPolicyCancel);
            }];
            return;
        }
    }
    
    // 补充添加 “打电话” “发短信” “发邮件功能”
    NSArray *funsArray = @[@"tel" ,@"sms" ,@"mailto"];
    if ([funsArray containsObject:url.scheme]){
        if ([application canOpenURL:url]){
            [application openURL:url options:@{} completionHandler:^(BOOL success) {
                decisionHandler(WKNavigationActionPolicyCancel);
            }];
            return;
        }
    }
    
    // Using [bendytree/Objective-C-RegEx-Categories](https://github.com/bendytree/Objective-C-RegEx-Categories) to check URL String
    //#import "RegExCategories.h"
    // iTunes: App Store link 允许跳转到 AppStore/其他App
    NSString *urlString = (url) ? url.absoluteString : @"";
    
    BOOL(^isMatch)(NSString *,NSString *,BOOL) = ^BOOL(NSString *url ,NSString *rx ,BOOL ignoreCase){
        NSRegularExpression *express = [[NSRegularExpression alloc] initWithPattern:rx options:ignoreCase ? NSRegularExpressionCaseInsensitive : 0 error:nil];
        return [express numberOfMatchesInString:urlString options:0 range:NSMakeRange(0, urlString.length)] > 0;
    };
    if (isMatch(urlString ,@"\\/\\/itunes\\.apple\\.com\\/" ,NO)) {
        [application openURL:url options:@{} completionHandler:^(BOOL success) {
            decisionHandler(WKNavigationActionPolicyCancel);
        }];
        return;
    }// Protocol/URL-Scheme without http(s)
    else if (!isMatch(urlString ,@"^https?:\\/\\/." ,YES)) {
        [application openURL:url];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    if (self.webViewUrlRouteBlock) {
        self.webViewUrlRouteBlock(navigationAction, decisionHandler);
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}

//  当Web视图加载内容时发生错误时调用。
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    if (self.webViewLoadErrorBlock) {
        self.webViewLoadErrorBlock(webView, error);
    }
}

//  导航完成后调用。
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    if (self.webViewFinishLoadBlock) {
        self.webViewFinishLoadBlock(webView);
    }
}

#pragma mark - WKUIDelegate
//  创建一个新的网页视图。
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView loadRequest:navigationAction.request];
    }
    return nil;
}

//  显示一个JavaScript警报面板。
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {

}

//  显示一个JavaScript确认面板。
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler {

}

//  显示一个JavaScript文本输入面板。
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler {

}

- (void)startTTS:(NSString *)content voicer:(NSString *)voicer{
    if (_audioPlayer != nil && _audioPlayer.isPlaying == YES) {
        [_audioPlayer stop];
    }
    
    //set TTS speaker
    [_iFlySpeechSynthesizer setParameter:voicer forKey:[IFlySpeechConstant VOICE_NAME]];
    [_iFlySpeechSynthesizer startSpeaking:content];
}


/// 开始录音
/// - Parameters:
///   - time1: 最长录制时间
///   - time2: 中断录制自动结束的中断时长
///   - time3: 多久不说话自动结束
- (void)startRecord:(NSInteger)time1 time2:(NSInteger)time2 time3:(NSInteger)time3{
    // 设置评测前端点超时
    [self.iFlySpeechEvaluator setParameter:[NSString stringWithFormat:@"%ld",(long)time1] forKey:[IFlySpeechConstant VAD_BOS]];
    // 设置评测后端点超时
    [self.iFlySpeechEvaluator setParameter:[NSString stringWithFormat:@"%ld",(long)time2] forKey:[IFlySpeechConstant VAD_EOS]];
    // 设置评测超时
    [self.iFlySpeechEvaluator setParameter:[NSString stringWithFormat:@"%ld",(long)time3]  forKey:[IFlySpeechConstant SPEECH_TIMEOUT]];
    
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    NSLog(@"text encoding:%@",[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant TEXT_ENCODING]]);
    NSLog(@"language:%@",[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant LANGUAGE]]);
    
 
     NSMutableData *buffer = [NSMutableData dataWithData:[self.recordWord dataUsingEncoding:encoding]];
    NSLog(@" \nen buffer length: %lu",(unsigned long)[buffer length]);
 
    
   BOOL ret = [self.iFlySpeechEvaluator startListening:buffer params:nil];
    if(ret){
        //Set audio stream as audio source,which requires the developer import audio data into the recognition control by self through "writeAudio:".
        //set the category of AVAudioSession
       [IFlyAudioSession initRecordingAudioSession];
       
       _pcmRecorder.delegate = self;
       
       //start recording
       BOOL ret = [_pcmRecorder start];
       
       NSLog(@"%s[OUT],Success,Recorder ret=%d",__func__,ret);
    }
}

- (void)stopRecord{
    [_pcmRecorder stop];
    [self.iFlySpeechEvaluator stopListening];
}

#pragma mark - IFlySpeechSynthesizerDelegate
- (void)onSpeakBegin
{
    
}

- (void)onBufferProgress:(int) progress message:(NSString *)msg
{
    NSLog(@"buffer progress %2d%%. msg: %@.", progress, msg);
}

- (void) onSpeakProgress:(int) progress beginPos:(int)beginPos endPos:(int)endPos
{
    NSLog(@"speak progress %2d%%, beginPos=%d, endPos=%d", progress,beginPos,endPos);
}

- (void)onSpeakPaused
{
    
}

- (void)onCompleted:(IFlySpeechError *) error
{
//    NSFileManager *fm = [NSFileManager defaultManager];
//    if ([fm fileExistsAtPath:_uriPath]) {
//        NSError *error = nil;
//        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
//        NSLog(@"%@",error);
//        _audioPlayer = [[PcmPlayer alloc] initWithFilePath:_uriPath sampleRate:16000];
//        [_audioPlayer play];
//    }
}

#pragma mark - ISESettingDelegate

/*!
 *  callback of ISE setting
 */
- (void)onParamsChanged:(ISEParams *)params {
 
}

#pragma mark - IFlySpeechEvaluatorDelegate

/*!
 *  volume callback,range from 0 to 30.
 */
- (void)onVolumeChanged:(int)volume buffer:(NSData *)buffer {
    NSLog(@"volume:%d",volume);
 
}

/*!
 *  Beginning Of Speech
 */
- (void)onBeginOfSpeech {
    
 
    
}

/*!
 *  End Of Speech
 */
- (void)onEndOfSpeech {
    
}

/*!
 *  callback of canceling evaluation
 */
- (void)onCancel {
    
}

 

/*!
 *  result callback of speech evaluation
 *  results：evaluation results
 *  isLast：whether or not this is the last result
 */
- (void)onResults:(NSData *)results isLast:(BOOL)isLast{
    
    if (results) {
        NSString *showText = @"";
        
        const char* chResult=[results bytes];
        
        BOOL isUTF8=[[self.iFlySpeechEvaluator parameterForKey:[IFlySpeechConstant RESULT_ENCODING]]isEqualToString:@"utf-8"];
        NSString* strResults=nil;
        if(isUTF8){
            strResults=[[NSString alloc] initWithBytes:chResult length:[results length] encoding:NSUTF8StringEncoding];
        }else{
            NSLog(@"result encoding: gb2312");
            NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
            strResults=[[NSString alloc] initWithBytes:chResult length:[results length] encoding:encoding];
        }
        if(strResults){
            showText = [showText stringByAppendingString:strResults];
        }
        NSLog(@"%@",showText);
//        [self.xmlParser parserXml:showText];
        
        NSError *error;
        NSDictionary *resDict = [XMLReader dictionaryForXMLString:showText error:&error];
        NSLog(@"%@",resDict);

        if (self.isStopRecord){
            NSDictionary *dataDict = resDict[@"xml_result"][@"read_sentence"][@"rec_paper"][@"read_chapter"];
            NSMutableDictionary *_dataDataDict = [NSMutableDictionary dictionaryWithDictionary:dataDict];
            if (dataDict){
                NSInteger accuracy_score = [dataDict[@"accuracy_score"]intValue];
                [_dataDataDict setObject:@(accuracy_score) forKey:@"accuracy_score"];
                
                NSInteger total_score = [dataDict[@"total_score"]intValue];
                [_dataDataDict setObject:@(total_score) forKey:@"total_score"];
                
                NSInteger standard_score = [dataDict[@"standard_score"]intValue];
                [_dataDataDict setObject:@(standard_score) forKey:@"standard_score"];
                
                NSInteger fluency_score = [dataDict[@"fluency_score"]intValue];
                [_dataDataDict setObject:@(fluency_score) forKey:@"fluency_score"];
                
                NSString *encodeString = [[dataDict mj_JSONString] ks_URLEncodedString];
                NSString *jsString = [NSString stringWithFormat:@"javascript:recordFinishCallback(\"%@\")", encodeString];
                 [self.webView evaluateJavaScript:jsString completionHandler:^(id _Nullable data, NSError * _Nullable error) {

                }];
            }
        }
    }
    else{
 
    }
}

#pragma mark - ISEResultXmlParserDelegate

-(void)onISEResultXmlParser:(NSXMLParser *)parser Error:(NSError*)error{
    
}

-(void)onISEResultXmlParserResult:(ISEResult*)result{
    NSLog(@"%@",[result toString]);
}


#pragma mark - IFlyPcmRecorderDelegate

- (void) onIFlyRecorderBuffer: (const void *)buffer bufferSize:(int)size
{
    NSData *audioBuffer = [NSData dataWithBytes:buffer length:size];
    
    int ret = [self.iFlySpeechEvaluator writeAudio:audioBuffer];
    if (!ret)
    {
        [self.iFlySpeechEvaluator stopListening];
    }
}

- (void) onIFlyRecorderError:(IFlyPcmRecorder*)recoder theError:(int) error
{
    
}

//range from 0 to 30
- (void) onIFlyRecorderVolumeChanged:(int) power
{
    NSLog(@"%d",power);
}


@end
